package com.iuie.ns.frame.utils.httpclients;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TimeZone;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.iuie.ns.frame.exception.ServiceException;
import com.iuie.ns.frame.utils.StringUtils;

/**
 * httpPut请求
 * @author liujie
 * @date 2018年6月2日下午5:22:41
 */
class HttpPutRequest implements IHttpRequest {
	
	private static final Logger logger = LoggerFactory.getLogger(HttpPutRequest.class);

	@Override
	public HttpResult send(HttpParams params) {
		try {
			Object oParams = params.params();
			String url = params.url();
			
			if (StringUtils.isBlank(url)) {
				throw new ServiceException("ERR: httpPut请求失败，URL为空！");
			}
			
			// 拼接参数
			HttpEntity httpEntity = null;
			if (oParams != null ) {
				ContentType contentType = params.contentType();
				// 字符型
				if (contentType == ContentType.JSON || contentType == ContentType.TEXT || contentType == ContentType.X_WWW_FORM_URLENCODED) {
					if (oParams instanceof Map) {
						// 如果是map
						@SuppressWarnings("unchecked")
						Map<String, Object> mParams = (Map<String, Object>) oParams;
						if (mParams != null && !mParams.isEmpty()) {
							List<NameValuePair> pairs = new ArrayList<NameValuePair>(mParams.size());
							for (String key : mParams.keySet()) {
								pairs.add(new BasicNameValuePair(key, mParams.get(key).toString()));
							}
							httpEntity = new UrlEncodedFormEntity(pairs);
						}
					} else {
						// 否则转json进行传输
						ObjectMapper mapper = new ObjectMapper();
						mapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
						String s = mapper.writeValueAsString(oParams);
						httpEntity = new StringEntity(s, params.charset());
						((StringEntity)httpEntity).setContentType(params.contentType().value());
					}
				}
				// 字节流
				if (contentType == ContentType.MULTIPART_FORM_DATA) {
					if (oParams instanceof Map) {
						// 如果是map
						@SuppressWarnings("unchecked")
						Map<String, Object> mParams = (Map<String, Object>) oParams;
						if (mParams != null && !mParams.isEmpty()) {
							MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
							multipartEntityBuilder.setMode(HttpMultipartMode.RFC6532);
							Iterator<Entry<String, Object>> it = mParams.entrySet().iterator();
							while (it.hasNext()) {
								Entry<String, Object> en = it.next();
								String key = en.getKey();
								Object value = en.getValue();
								if (value != null) {
									if (value instanceof File) {
										multipartEntityBuilder.addBinaryBody(key, (File)value);
									} else if (value instanceof byte[]) {
										multipartEntityBuilder.addBinaryBody(key, (byte[])value);
									} else if (value instanceof InputStream) {
										multipartEntityBuilder.addBinaryBody(key, (InputStream)value);
									} else {
										multipartEntityBuilder.addTextBody(key, String.valueOf(value));
									}
								}
								
							}
							httpEntity = multipartEntityBuilder.build();
						}
					}
				}
			}
			
			HttpPut httpPut = new HttpPut(url);
			httpPut.setEntity(httpEntity);
			
			// 设置HTTP请求头
			Map<String, String> headers = params.headers();
			headers.put("Accept", "*/*");
			headers.put("Accept-Encoding", "gzip, deflate, sdch");
			headers.put("Accept-Language", "zh-CN,zh;q=0.8");
			
			Iterator<Entry<String, String>> it = headers.entrySet().iterator();
			while (it.hasNext()) {
				Entry<String, String> en = it.next();
				httpPut.setHeader(en.getKey(), en.getValue());
			}
			
			// 设置超时时间
			RequestConfig config = RequestConfig.custom()
				.setConnectTimeout(params.connectTimeout())
				.setSocketTimeout(params.socketTimeout()).build();
			httpPut.setConfig(config);
			
			// 发送httpPost请求
			CloseableHttpClient client = HttpClients.createDefault();
			CloseableHttpResponse resp = null;
			try {
				resp = client.execute(httpPut);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
				throw new ServiceException("httpPut请求失败，UnsupportedEncodingException");
			} catch (ClientProtocolException e) {
				e.printStackTrace();
				throw new ServiceException("httpPut请求失败，ClientProtocolException");
			} catch (IOException e) {
				e.printStackTrace();
				throw new ServiceException("httpPut请求失败，IOException");
			}
			
			// 获取并返回响应信息
			return new HttpResult(resp.getEntity(), client, resp);
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("ERR:执行httpPut请求异常<br>url={}, 参数={}", params.url(), params.params());
			throw new ServiceException("ERR:执行httpPut请求异常<br>url=" + params.url());
		}
	}

}
